package cRpc

import (
	"fmt"
	"reflect"
	"sync"

	"google.golang.org/grpc"
)

type RpcClientContainer struct {
	lock      sync.RWMutex
	instances map[string]any

	signature string
	hosts     map[string]string
	grpc      map[string]grpc.ClientConnInterface
}

func (i *RpcClientContainer) Save(instance any) bool {
	i.lock.Lock()
	defer i.lock.Unlock()

	pkg, app, service := instance.(RpcClientInterface).RpcClientName()
	index := pkg + "." + app + "." + service
	i.instances[index] = instance

	return true
}

func (i *RpcClientContainer) Get(name string) any {
	i.lock.RLock()
	defer i.lock.RUnlock()

	return i.instances[name]
}

func (i *RpcClientContainer) Remove(name string) bool {
	i.lock.Lock()
	defer i.lock.Unlock()

	delete(i.instances, name)

	return true
}

func (i *RpcClientContainer) Is(instance any) bool {
	return reflect.TypeOf(instance).Implements(reflect.TypeOf((*RpcServiceInterface)(nil)).Elem())
}

func (i *RpcClientContainer) Range(f func(instance any)) {
	i.lock.RLock()
	defer i.lock.RUnlock()

	for _, item := range i.instances {
		f(item)
	}
}

func (i *RpcClientContainer) GetHost(pkg, app, name string) (host string) {
	index := fmt.Sprintf("%s.%s.%s", pkg, app, name)
	return i.hosts[index]
}

func (i *RpcClientContainer) SetSignature(signature string) {
	i.signature = signature
}

func (i *RpcClientContainer) GetSignature() string {
	return i.signature
}

func (i *RpcClientContainer) GetGRPCConnection(pkg, app, name string) grpc.ClientConnInterface {
	index := fmt.Sprintf("%s.%s.%s", pkg, app, name)
	return i.grpc[index]
}

var client_container = &RpcClientContainer{
	lock:      sync.RWMutex{},
	instances: make(map[string]any),
	signature: "",
	hosts:     make(map[string]string),
	grpc:      make(map[string]grpc.ClientConnInterface),
}
